package edu.ptu.acl.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import edu.ptu.acl.common.AdminValidate;
import edu.ptu.acl.common.MyConstants;
import edu.ptu.acl.common.RequestHolder;
import edu.ptu.acl.common.ResultVO;
import edu.ptu.acl.dto.AclTreeDto;
import edu.ptu.acl.entity.Acl;
import edu.ptu.acl.entity.RoleAcl;
import edu.ptu.acl.mapper.AclMapper;
import edu.ptu.acl.mapper.RoleAclMapper;
import edu.ptu.acl.service.IAclService;
import edu.ptu.acl.service.ILogService;
import edu.ptu.acl.service.IRoleAclService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author LinJC
 * @since 2022-03-15
 */
@Service
public class RoleAclServiceImpl extends ServiceImpl<RoleAclMapper, RoleAcl> implements IRoleAclService {

    @Resource
    private IAclService aclService;
    @Resource
    private RoleAclMapper roleAclMapper;
    @Resource
    private AclMapper aclMapper;
    @Resource
    private ILogService logService;

    @Override
    public HashMap<String, Object> getRoleAclTree(Long roleId) {
        List<Acl> aLLAclList = aclMapper.selectList(null);

        // 得到该角色的roleAcl关系List
        QueryWrapper<RoleAcl> roleAclQueryWrapper = new QueryWrapper<>();
        roleAclQueryWrapper.eq("role_id",roleId);
        List<RoleAcl> roleAclList = roleAclMapper.selectList(roleAclQueryWrapper);
        // 得到角色的所拥有的aclId列表
        Set<Long> roleAclIds = roleAclList.stream().map(RoleAcl::getAclId).collect(Collectors.toSet());

        // 该角色拥有的aclId列表，返回给前端
        Set<String> checkedAclIds = new HashSet<>();
        // dto列表，把所有acl转成dto
        List<AclTreeDto> aclTreeDtoList = new ArrayList<>();
        // 获取当前登陆用户拥有的权限列表
        List<Acl> currentUserAclList = aclService.getCurrentUserAclList();
        Set<Long> currentUserAclIds = currentUserAclList.stream().map(Acl::getId).collect(Collectors.toSet());
        for (Acl acl : aLLAclList) {

            AclTreeDto aclTreeDto = AclTreeDto.copyDept(acl);

            // 处理冻结的acl
            if (StringUtils.equals(acl.getStatus(), MyConstants.AclStatus.FREEZE.getId())){
                // 设为不可选择
                aclTreeDto.setNoAcl(true);
                aclTreeDtoList.add(aclTreeDto);
                continue;
            }

            // 如果角色拥有该权限，添加进列表
            if (roleAclIds.contains(aclTreeDto.getId())) {
                aclTreeDto.setChecked(true);
                checkedAclIds.add(aclTreeDto.getId().toString());
            }

            // 根据当前登陆用户拥有的权限赋予noAcl值
            if (AdminValidate.isAdmin() || currentUserAclIds.contains(aclTreeDto.getId())) {
                aclTreeDto.setNoAcl(false);
            }

            aclTreeDtoList.add(aclTreeDto);
        }

        // 把数据转成树状结构
        List<AclTreeDto> rootAclTreeDtoList = list2Tree(aclTreeDtoList);

        HashMap<String, Object> result = new HashMap<>();
        result.put("aclTree",rootAclTreeDtoList);
        result.put("checkedAclIds",checkedAclIds);

        return result;
    }



    private List<AclTreeDto> list2Tree(List<AclTreeDto> aclTreeDtoList) {
        Multimap<Long, AclTreeDto> aclTreeDtoMultimap = ArrayListMultimap.create();

        for (AclTreeDto treeDto : aclTreeDtoList) {
            aclTreeDtoMultimap.put(treeDto.getParentId(),treeDto);
        }

        List<AclTreeDto> rootAclTreeDtoList = (List<AclTreeDto>)aclTreeDtoMultimap.get(0L);
        Collections.sort(rootAclTreeDtoList,(d1, d2) -> d1.getSeq()-d2.getSeq());

        aclService.recursionAclTree(rootAclTreeDtoList,aclTreeDtoMultimap);

        return rootAclTreeDtoList;
    }
    @Override
    public void updateRoleAcl(Long roleId, List<Long> aclIds) {
        // todo:做一下判断，如果没修改就不要做插入了

        QueryWrapper<RoleAcl> roleAclQueryWrapper = new QueryWrapper<>();
        roleAclQueryWrapper.eq("role_id",roleId);
        List<RoleAcl> beforeRoleAclList = roleAclMapper.selectList(roleAclQueryWrapper);
        roleAclMapper.delete(roleAclQueryWrapper);

        if (CollectionUtils.isEmpty(aclIds)){
            logService.saveRoleAclLog(roleId,beforeRoleAclList.stream().map(RoleAcl::getAclId).collect(Collectors.toList()), null);
            return;
        }

        // todo:改成批量插入
        for (Long aclId : aclIds) {
            roleAclMapper.insert(new RoleAcl(roleId,aclId));
        }
        logService.saveRoleAclLog(roleId,beforeRoleAclList.stream().map(RoleAcl::getAclId).collect(Collectors.toList()),
                aclIds);
    }
}
